package
{
	import flash.desktop.NativeApplication;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.setInterval;
	
	import as3sdk.utils.UtilXMLParse;
	
	/**
	 * 
	 * @author hanxianming
	 * 
	 */	
	public class XML2ObjectTool extends Sprite
	{

		private var _fileList:Array;
		private var _urlLoader:URLLoader;
		private var _urlRequest:URLRequest;
		private var _configByteArray:ByteArray;
		private var _urlConfigLoader:URLLoader;
		
		private var loadConfigList:Vector.<FolderNode>;
		
		private var _curFolderNode:FolderNode;
		
		private var _appXML:String = "XML2ObjectTool.xml";
		
		private var _appBat:String = "app.bat";
		
		private var _configCompress:String = "configCompress.xml";
		
		private var _curAppId:String;
		
		private var _configNumber:int;
		
		public function XML2ObjectTool()
		{
			initizlize();
		}
		
		private function initizlize():void
		{
			
			_urlRequest = new URLRequest();
			
			_urlConfigLoader = new URLLoader();
			_urlConfigLoader.dataFormat = URLLoaderDataFormat.TEXT;
			_urlConfigLoader.addEventListener(Event.COMPLETE, urlConfigLoaderCompleteHandler);
			
			_urlRequest.url = "configCompress.xml";
//			_urlRequest.url = _appXML;
			_urlConfigLoader.load(_urlRequest);
			
			
			_urlLoader = new URLLoader();
			
			_urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
			_urlLoader.addEventListener(Event.COMPLETE, urlLoaderCompleteHandler);
			
			_configByteArray = new ByteArray();
			
			trace("[info] compressing......");
			
		}
		
		protected function urlConfigLoaderCompleteHandler(event:Event):void
		{
			/*if(_urlRequest.url == _appXML)
			{
				clearApplication();
				saveAppXML(_urlConfigLoader.data);
				saveAppBat(null);
			}
			else if(_urlRequest.url == _appBat)
			{
				saveAppBat(_urlConfigLoader.data);
			}
			else
			{*/
				loadConfigList = new Vector.<FolderNode>();
				
				var xml:XML = new XML(_urlConfigLoader.data);
				var configObject:Object = xml2Object(xml);
				
				var tempFile:File;
				var folderNode:FolderNode;
				
				for each (var item:Object in configObject) 
				{
					if (item is String)
					{
						continue;
					}
					
					tempFile = File.applicationDirectory;
					tempFile.url = tempFile.url + item["folder"];
					
					folderNode = new FolderNode();
					folderNode.exportName = item.exportName;
					folderNode.copyMoveTarget = item.copyMoveTarget;
					folderNode.folder = item.folder;
					try
					{
						folderNode.fileList = tempFile.getDirectoryListing();
					} 
					catch(error:Error) 
					{
						trace("[error] File.getDirectoryListing() error  " + tempFile.nativePath);
						continue;
					}
					for each (var item1:Object in item) 
					{
						if (item1 is String)
						{
							continue;
						}
						folderNode.compressList.push(item1["configName"]);
					}
					
					loadConfigList.push(folderNode);
				}
				
				loadFolder();
			/*}*/
			
		}
		
		/*private function clearApplication():void
		{
			var tempFile:File = File.applicationDirectory;
			
			if (!tempFile.exists)
			{
				return;
			}
			
			var tempFileList:Array = tempFile.getDirectoryListing();
			var len:int = tempFileList.length;
			for (var i:int = 0; i < len; i++) 
			{
				var file:File = tempFileList[i];
				if(file.extension == "xml" && file.name.indexOf("XML2ObjectTool") != -1 && file.name.indexOf(".xml") != -1)
				{
					try
					{
						file.deleteFile();
					} 
					catch(error:Error) 
					{
						trace("not delete:" + file.nativePath);
					}
				}
			}
		}
		
		private function saveAppBat(data:String):void
		{
			var appBatContent:String = "adl -runtime runtimes/\air/\win " + _curAppId +  ".xml -nodebug";
			var fileStream:FileStream = new FileStream();
			try 
			{
				var tempFile:File = File.applicationDirectory;
				tempFile.nativePath = tempFile.nativePath + File.separator + "app.bat";
				fileStream.open(tempFile, FileMode.WRITE);
				fileStream.writeUTFBytes(appBatContent);
				fileStream.close();
			}catch (e:Error) 
			{
				trace(e.getStackTrace());
			}
			fileStream = null;
			
			_urlRequest.url = _configCompress;
			_urlConfigLoader.load(_urlRequest);
		}
		
		private function saveAppXML(xmlString:String):void
		{
			_urlConfigLoader.close();
			
			var pattern:RegExp = /<id>.*?<\/id>/;
			_curAppId = "XML2ObjectTool-" + new Date().getTime();
			xmlString = xmlString.replace(pattern, "<id>" + _curAppId +"</id>");
			
			var fileStream:FileStream = new FileStream();
			try 
			{
				var tempFile:File = new File(File.applicationDirectory.nativePath);
				
				var tempPath:String = tempFile.nativePath; 
				
				tempFile.nativePath = tempPath + File.separator + _curAppId + ".xml";
				fileStream.open(tempFile, FileMode.WRITE);
				fileStream.writeUTFBytes(xmlString);
				fileStream.close();
				
			}catch (e:Error) 
			{
				trace(e.getStackTrace());
			}
			fileStream = null;
			
			_urlRequest.url = _configCompress;
			_urlConfigLoader.load(_urlRequest);
		}*/
		
		private function loadFolder():void
		{
			if (loadConfigList.length <= 0)
			{
				trace("[info] all completed......" + new Date().toString());
				return;
			}
			
			_curFolderNode = loadConfigList.shift();
			
			_fileList = _curFolderNode.fileList;
			
			_configNumber = _fileList.length;
			
			loadFileList();
		}
		
		protected function urlLoaderCompleteHandler(event:Event):void
		{
			var xml:XML = new XML(_urlLoader.data);
			var configObject:Object;
			var noComperss:Boolean = _curFolderNode.compressList.every(function (item:String, index:int, vector:Vector.<String>):Boolean
			{
				var tmepUrl:String = _urlRequest.url; 
				if (tmepUrl.indexOf(item) != -1)
				{
					configObject = xml2Object(xml);
					return false;
				}
				return true;
			});
			
			if (noComperss)
			{
				configObject = xml;
				trace("[info] completed......" + xml.attribute("name").toString() + " uncompression");
			}
			
			_configByteArray.writeObject(configObject);
			
			
			loadFileList();
			
		}
		
		private function loadFileList():void
		{
			if (_fileList.length <= 0)
			{
				saveFile();				
				loadFolder();
				return;
			}
			
			var tempFile:File;
			
			tempFile = _fileList.pop();
			
			if (tempFile.isDirectory)
			{
				loadFileList();
				return;
			}
			
			_urlRequest.url = tempFile.url;
			
			_urlLoader.load(_urlRequest);
			
		}
		
		private function saveFile():void
		{
			if (_curFolderNode == null)
			{
				return;
			}
			
			var fileStream:FileStream;
			
			_configByteArray.writeShort(_configNumber);
			_configByteArray.compress();
			_configByteArray.position = 0;
			
			try 
			{
				trace("[info] " + " create " + _curFolderNode.exportName + ".....");
				var tempFile:File = File.applicationDirectory;
				tempFile.nativePath = tempFile.nativePath + File.separator + _curFolderNode.exportName;
				fileStream = new FileStream();
				fileStream.open(tempFile, FileMode.WRITE);
				fileStream.writeBytes(_configByteArray);
				fileStream.close();
				
				trace("[info] " + " copyMove " + _curFolderNode.copyMoveTarget + ".....");

				_configByteArray.position = 0;
				tempFile = File.applicationDirectory;
				tempFile.nativePath = _curFolderNode.copyMoveTarget;
				fileStream = new FileStream();
				fileStream.open(tempFile, FileMode.WRITE);
				fileStream.writeBytes(_configByteArray);
				fileStream.close();
				
			}catch (e:Error) 
			{
				trace("[error] fileStream error：" + tempFile.nativePath);
			}
			fileStream = null;
			_configByteArray.clear();
			
			
			trace("[info] " + _curFolderNode.exportName + " complete.....");
//			trace("[info] 3 seconds auto exit.....");
			
//			tempFile.openWithDefaultApplication();
			
			
			NativeApplication.nativeApplication.exit();
//			setInterval(function():void
//			{
//				NativeApplication.nativeApplication.exit();
//			}, 3000);
				
		}
		
		public static function xml2Object(xml:XML):Object
		{
			return UtilXMLParse.xml2Object(xml);
		}
	}
}


class FolderNode
{
	public var exportName:String;
	public var folder:String;
	public var compressList:Vector.<String> = new Vector.<String>();
	public var fileList:Array;
	public var copyMoveTarget:String;
}